
class RunTests

  attr_accessor :test_cases

  def fw_tests e
    tests = FwTest.all
    if e.request['suite']
      suite_name = e.request['suite'].split('-').join('::')
      tests = tests.select { |t| t.to_s == suite_name }
    end
    run_tests tests
  end

  def app_tests e
    tests = AppTest.all
    if e.request['suite']
      suite_name = e.request['suite'].split('-').join('::')
      tests = tests.select { |t| t.to_s == suite_name }
    end
    run_tests tests
  end

  def run_tests tests
    class_name = tests.length == 1 ? "one" : "all"
    output = tests.collect { |test|
      ::Test::Unit::UI::Html::TestRunner.run(test)
    }.join("\n")

    <<CSS
  <style>
    .tests {
    }
    .result {
      padding:0.25em;
      margin-bottom:1px;
      color:white;
    }
    .result .result-heading {
      font-family:consolas, 'cuourier new';
    }
    .result-red { background:red }
    .faults {
      margin:0;
      margin-top:0.25em;
      padding:0.5em;
      background:white; color:black;
      overflow:auto;
    }
    .fault  {
      margin-top:0.5em;
      margin-bottom:1em;
    }
    .fault .heading {
      /*background-color:yellow;*/
      padding:0.3em;
    }
    .fault .trace {
      padding-left:1.5em;
      padding-top:0.25em;
      font-size:0.9em;
      color:#777;
      font-family:consolas, 'cuourier new';
    }
    .result-green {
      background:green
    }
    .result a {
     color:white;
     text-decoration:none;
    }
    .result a:visited {
     color:white
    }
  </style>
CSS
    
    <<HTML
<div class="tests tests-#{class_name}">
  #{output}
</div>

HTML
  end

  def test_cases
    @tests || Testing::TestCase.all
  end

end



require 'test/unit/ui/testrunnermediator'
require 'test/unit/ui/testrunnerutilities'


module ::Test
module Unit
module UI
module Html

# Runs a Test::Unit::TestSuite on the console.
class TestRunner
  extend TestRunnerUtilities

  def self.run(test)
    super(test)
    @@output.join('')
  end

  # Creates a new TestRunner for running the passed
  # suite. If quiet_mode is true, the output while
  # running is limited to progress dots, errors and
  # failures, and the final result. io specifies
  # where runner output should go to; defaults to
  # STDOUT.
  def initialize(suite, output_level=NORMAL, io=STDOUT)
    if (suite.respond_to?(:suite))
      @suite = suite.suite
    else
      @suite = suite
    end
    @output_level = output_level
    @io = io
    @@output = []
    @faults = []
    @name = nil
    @progress_indication = ''
  end

  # Begins the test run.
  def start
    #output_raw("<pre style='font-family:consolas, courier new'>")
    setup_mediator
    attach_to_mediator
    return start_mediator
  end

  private
    def setup_mediator
    @mediator = create_mediator(@suite)
    suite_name = @suite.to_s
    if @suite.kind_of?(Module)
      suite_name = @suite.name
    end
    @suite_name = suite_name
    #puts suite_name
  end

  def create_mediator(suite)
    return TestRunnerMediator.new(suite)
  end

  def attach_to_mediator
    @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
    @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
    @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
    @mediator.add_listener(TestCase::STARTED, &method(:test_started))
    @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
  end

  def start_mediator
    return @mediator.run_suite
  end

  def add_fault(fault)
    @faults << fault
    @progress_indication << fault.single_character_display
  end

  def started(result)
    @result = result
  end

  def finished(elapsed_time)
    @color = has_faults? ? 'result-red' : 'result-green'
    @html = []
    @html << '<div class="unit-test">'
    @html << '<div class="result '+@color+'">'
    @html << "<span class=\"result-heading\">"+
      "<a href=\"?suite=#{@suite_name.split("::").join("-")}\">#{@suite_name}</a>"
    @html << ' '+@progress_indication

    form = el(:form, :action => '/admin/terminal/', :method => 'post', :class => 'run_in_terminal')
    form << el(:input, :type => 'submit', :value => "open in terminal")
    form << el(:input, :type => 'hidden', :name => 'command', :value => @suite_name+'.run.print')

    @html << form.to_s

    @html << '</span>'
    if has_faults?
      @html << '<div class="faults">'
      @faults.each_with_index do |fault, index|
        @html << "\n"+(display_fault fault, index)
      end
      @html << '</div>'
    end
    #@html << @result.to_s
    @html << '</div>'
    @html << '</div>'
    @@output = @html
  end

  def display_fault fault, index
    test = fault.test_name.
      split("(").first.
      split("_").tail.tap { |w| w[0].capitalize! }.join(" ")
    
    if fault.respond_to? :exception
      message = (format_message fault.exception.message.split("\n").first) +
        " (" + (fault.exception.class.to_s)+")."
    else
      message = format_message fault.message
    end

    #CGI.escapeHTML('%3d) %s' %

    ['<div class="fault">',
      '<span class="heading">',
        "<strong>#{test}</strong>: ",
        "<span class=\"message\">#{message}</span>",
      '</span>',
      "<div class=\"trace\">"+display_trace(fault)+"</div>",
      '</div>'
    ].join("\n")
  end

  def format_message words
     CGI.escapeHTML first_letter_up words
  end

  def display_trace fault
    fault_trace(fault).tap { |lines|
      if lines[0] # happens when no tests were specified
        lines [0] = "<span class=\"first\">"+lines[0]+"</span>"
      end
    }.join("<br/>")
  end

  def first_letter_up word
    word.chars.to_a.tap { |f| f[0].upcase! }.join
  end

  def fault_trace fault
    trace = fault.instance_variable_get('@location') || (fault.filter_backtrace fault.exception.backtrace)
    trace.map { |line|
      if line.include? 'bundler_gems'
        #"gems/" +  line.split("gems/").last
        nil
      elsif line.include?(__FILE__) || line.include?('/testing/tests.rb')
        nil
      else
        line
      end
    }.compact
  end

  def has_faults?
    @faults.length > 0
  end

  def test_started(name)
    #output_single(name + ": ", VERBOSE)
  end

  def test_finished(name)
    @progress_indication << '.'
  end

end
end
end
end
end

